/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package objects;

import Serializable.ParsedCmd;
import editor.WorldQ;
import graphic.PointerTransform;
import input.ActionState;
import java.util.ArrayList;
import java.util.Date;
import klient.Klient;
import java.util.LinkedList;
import java.util.List;
import klient.Bridge;
import org.lwjgl.util.vector.Vector3f;

/**
 *
 * @author bwplo_000
 */
public class ActionEngine {
    public List<MobInfo> Mobs = new LinkedList<>();
    public List<MobInfo> killQuerry = new LinkedList<>();
    public List<Tower>Towers = new LinkedList<>(); 
    public List<List<TowerCollisionArea>> CheckpointRegister;  
    public List<Tower>TowersToBuild = new ArrayList<>();
    private int TimeID;
    private WorldQ My; 
    @SuppressWarnings({"unchecked"})
    
    public ActionEngine(WorldQ my){
        this.My = my;
        CheckpointRegister = new LinkedList<>();
        for(int i=0; i<My.checkPoint.size(); i++){
            CheckpointRegister.add(new LinkedList<TowerCollisionArea>());
        }
        this.TimeID = TimeManager.register(100);
     
    }
    public void buildTower(int aTower, float x,float y, float z){
        Triangle t1=My.getTriangle(x+0.5f, z+0.5f);
        Triangle t2=My.getTriangle(x-0.5f, z-0.5f);
        
        Towers.add(new Tower(aTower,x,y,z));
        Towers.get(Towers.size()-1).build();
          
        Towers.get(Towers.size()-1).registerYourself(CheckpointRegister, My.checkPoint);
        t1.at=1; t2.at=1;
        
    }
    public void buildTower(int aTower){
           //PointerTransform.refresh();
        
        float px=PointerTransform.out.get(0)-PointerTransform.out.get(0)%2+1f;
        float pz=PointerTransform.out.get(2)-PointerTransform.out.get(2)%2+1f;
        float py=0;
        
          Triangle t1=My.getTriangle(px+0.5f, pz+0.5f);
          Triangle t2=My.getTriangle(px-0.5f, pz-0.5f);
          Tower t=(new Tower(aTower,px,py,pz));
        if(t1!=null && t2!=null && t1.at+t2.at==0 && Klient.uS.gold>=t.cost){
            if(Bridge.isMulti){
                ParsedCmd towerMsg = new ParsedCmd("NTOWER");
                towerMsg.floatParam=new float[]{px,py,pz};
                towerMsg.intParam=new int[]{Klient.uS.IDinGame,aTower};
                Bridge.req(towerMsg);
            }
                Towers.add(new Tower(aTower,px,py,pz));
                Towers.get(Towers.size()-1).build();
          
                Towers.get(Towers.size()-1).registerYourself(CheckpointRegister, My.checkPoint);
                t1.at=1; t2.at=1;
            Klient.uS.gold-=t.cost;
        }
    }
    public void addMob(Mob mob){
        mob.pos.x =  My.checkPoint.get(0).x;
        mob.pos.y =  My.checkPoint.get(0).y;
        mob.pos.z =  My.checkPoint.get(0).z;
        Mobs.add(0,new MobInfo(mob));
    }
    public void killMob(MobInfo mob){
        for(Tower tow:Towers){
            if(!tow.hasAim) {continue; }
            if(tow.checkAim(mob)){
                tow.removeAim();
            }
        }
        Mobs.remove(mob);
    }
    public void explodeMob(int ID){
        //System.out.println("I want BOOM ->" + ID);
        MobInfo act_m = null;
        for(MobInfo mob:Mobs){
            if(mob.M.getID() == ID){
                act_m = mob;
            }
        }
        if(act_m==null){ return;}
        //System.out.println("Found MOB! ->" + ID);
        for(Tower tow:Towers){
            if(!tow.hasAim) {continue; }
            if(tow.checkAim(act_m)){
                tow.removeAim();
            }
        }
        act_m.M.life = -1;
        act_m.M.setState(MobState.EXPLODE);
        //System.out.println("BOOM" + ID);
    }
    public void removeAims(MobInfo mob){   
        for(Tower tow:Towers){
            if(!tow.hasAim) {continue; }
            if(tow.checkAim(mob)){
                tow.removeAim();
            }
        }
    }
    public void draw(ActionState aState,int aTower,int player){
        for(Tower tow:Towers){      
                tow.draw(player);
        }
        for(MobInfo mob:Mobs){
            
                //kill mob at the end of the route
            if(mob.M.getState() != MobState.EXPLODE){
                if(mob.M.act_check_id>My.checkPoint.size()){

                        killQuerry.add(mob);
                        continue;
                }
                if(mob.M.life<=0){
                    removeAims(mob);
                    mob.M.setState(MobState.EXPLODE);
                    Klient.uS.gold+=mob.M.value;
                    if(Bridge.isMulti){
                        ParsedCmd cmd=new ParsedCmd("DMOB");
                        cmd.intParam=new int[]{Klient.uS.IDinGame,mob.M.getID()};
                        Bridge.req(cmd);
                    }
                    continue;
                }
            }else{
                if(mob.M.life == 100){
                    killQuerry.add(mob);
                    continue;
                }
            
            }
                
                 //if not -> draw Mob
                if(mob.M.act_check_id==My.checkPoint.size()){
                   mob.M.drawRealMode(My.checkPoint.get(My.checkPoint.size()-1),player == (Bridge.isMulti?Klient.uS.IDinGame:0));
                }else{
                    mob.M.drawRealMode(My.checkPoint.get(mob.M.act_check_id),player == (Bridge.isMulti?Klient.uS.IDinGame:0));
                }
        }
        //killing part of draw ):
        for(MobInfo mob:this.killQuerry){
               killMob(mob);
        }
        this.killQuerry.clear();
        
        
        if(aState == ActionState.BUILD){
          PointerTransform.refresh();
          
          float px=PointerTransform.out.get(0)-PointerTransform.out.get(0)%2+1f;
          float pz=PointerTransform.out.get(2)-PointerTransform.out.get(2)%2+1f;
          float py=0;
          Triangle t1=My.getTriangle(px+0.5f, pz+0.5f);
          Triangle t2=My.getTriangle(px-0.5f, pz-0.5f);
          
          if(t1!=null && t2!=null && t1.at+t2.at==0){
                TowersToBuild.get(aTower-1).move(px,py,pz);
                TowersToBuild.get(aTower-1).setTowerColor(TowersToBuild.get(aTower-1).goodPlaceC);
                TowersToBuild.get(aTower-1).draw(player);     
          }
          else{
              TowersToBuild.get(aTower-1).move(PointerTransform.out.get(0),0.0f,PointerTransform.out.get(2));
              TowersToBuild.get(aTower-1).setTowerColor(TowersToBuild.get(aTower-1).badPlaceC);
              TowersToBuild.get(aTower-1).draw(player); 
          }
        }
        //check collisions
        if(TimeManager.check(TimeID)){
             for(MobInfo mob:Mobs){
                 if(mob.M.getState() == MobState.EXPLODE){ continue; }
                 
                 if(mob.M.act_check_id-1 ==  CheckpointRegister.size()){continue;}
                 for(TowerCollisionArea tca : CheckpointRegister.get(mob.M.act_check_id-1)){
                     if(ActionEngine.isInSquare(tca, mob.M.pos)){
                         if(!tca.getTowerId().hasAim){
                             tca.getTowerId().setAim(mob,tca,tca);
                         }
                     }
                 }
             }
        }
    }
    public static Boolean isInSquare(TowerCollisionArea tca, Vector3f pos){
        Boolean oneState = false;
        if(tca.getTo().x - tca.getFrom().x > 0 ){
            if(pos.x <= tca.getTo().x+1.0f && pos.x >= tca.getFrom().x-1.0f){
                oneState = true;
            }
        }
        else{
           if(pos.x >= tca.getTo().x-1.0f && pos.x <= tca.getFrom().x+1.0f){
                oneState = true;
            } 
        }
        if(oneState){
            if(tca.getTo().z - tca.getFrom().z > 0 ){
                if(pos.z <= tca.getTo().z+1.0f && pos.z >= tca.getFrom().z-1.0f){
                    return true;
                }
            }
            else{
               if(pos.z >= tca.getTo().z-1.0f && pos.z <= tca.getFrom().z+1.0f){
                    return true;
                } 
            } 
        }
        return false;
    }
}
